#include "dnsimpl.h"

CDnsImpl::CDnsImpl()
{

}
CDnsImpl::~CDnsImpl(void)
{

}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
std_method_impl CDnsImpl::init_class(IBase* prot, IBase* punkOuter)
{
	HRESULT		hr = S_OK;
	if (prot != NULL)
	{
		m_pRot = prot;
	}
	return hr;
}
std_method_impl CDnsImpl::Init(void*)
{
	HRESULT		hr = S_OK;

	os_sem_init(&this->sem, 0);

	return hr;
}
std_method_impl CDnsImpl::Uninit()
{
	HRESULT		hr = S_OK;

	os_sem_destroy(&this->sem);

	return hr;
}
std_method_impl CDnsImpl::Start()
{
	HRESULT		hr = S_OK;

#if (TARGET_OS == OS_WINDOWS)
	WORD verision = MAKEWORD(2, 2);
	WSADATA lpData;
	int intEr = WSAStartup(verision, &lpData);
	if (intEr != 0)
	{
		return E_FAIL;
	}
#endif

	


	iosprintf("dns service start\n");
	dnsinit();
	ithread::start_thread();
	os_sem_wait(&this->sem);

	return hr;
}
std_method_impl CDnsImpl::Stop()
{
	HRESULT		hr = S_OK;

	dnsuninit();
	ithread::join();
	iosprintf("dns service end\n");



#if (TARGET_OS == OS_WINDOWS)
	if (WSACleanup() != 0)
	{
		return E_FAIL;
	}
#endif
	return hr;
}
//////////////////////////////////////////////////////////////////////////
//IDns
std_method_impl CDnsImpl::GetURLtoHost(	const char* url, const char* lastip,
										const char* name, IDnsProc* proc,
										int* cache, char* ip, int nocache)
{
	HRESULT		hr = S_OK;

	if (!nocache) {
		retrtpv(ip, E_FAIL)
		if (getiptable(url, lastip, ip)) {
			retrtpv(cache, E_FAIL)
			*cache = 1;
			return hr;
		}
	}

	retrtpv(url, E_FAIL)
	retrtpv(name, E_FAIL)
	retrtpv(proc, E_FAIL)

	if (!dnsreq(url, name, proc)) 
		return E_FAIL;
	return hr;
}
std_method_impl CDnsImpl::DnsSyncResultIP(const char* url, IDnsProc* proc)
{
	map<string, iplist>::iterator it = m_mapURLtoIPtable.find(url);
	if (it != m_mapURLtoIPtable.end()) {

		iplist find = (*it).second;
		iplist::iterator itlist = find.begin();

		while (itlist != find.end()) {

			HRESULT		hr = S_OK;
			hr = proc->DnsResultIP(DNS_PROC_RES_OK,url,(char*)((*itlist).c_str()));
			if (hr == E_FAIL) {
				break;
			}
			itlist++;
		}
		return S_OK;
	}
	proc->DnsResultIP(DNS_PROC_RES_ERROR, "", "");
	return E_FAIL;
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
void CDnsImpl::dns_func(void *pData, const char* name, const char* url, const char* ip, void* cb)
{
	setiptable(url, ip);
}
void CDnsImpl::dns_endfunc(void *pData, const char* name, const char* url, const char* ip, void* cb)
{
	retret(pData)
	retret(cb)

	IDnsProc* proc = static_cast<IDnsProc*>(cb);
	DnsSyncResultIP(url, proc);
	dnspro(DNS_PROC_RES_COMPLETE, url, ip, cb);
	dnsreqfree(pData);
}
void CDnsImpl::dns_errorfunc(void *pData, const char* name, const char* url, const char* ip, void* cb)
{
	dnspro(DNS_PROC_RES_ERROR, url, ip, cb);
}
void CDnsImpl::dns_signal(int istart)
{
	if (istart)
	{
		os_sem_post(&this->sem);
	}
}
void CDnsImpl::dnspro(int error, const char* url, const char* ip, void* cb)
{
	retret(cb)
	retret(ip)
	retret(url)

	IDnsProc* proc = static_cast<IDnsProc*>(cb);
	if (proc)
	{
		proc->DnsResultIP(error, url, ip);

	}
}

void CDnsImpl::run() 
{
	dnswait();
}
void CDnsImpl::threadstop() 
{

}
void CDnsImpl::setiptable(const char* url, const char* ip)
{
	CStackAutoCSLock lock(&m_Lock);

	retret(url)
	retret(ip)

	map<string, iplist>::iterator it = m_mapURLtoIPtable.find(url);
	if (it != m_mapURLtoIPtable.end()) {
		iplist* find = &it->second;
		find->push_back(ip);
		find->sort();
		find->unique();
	}
	else {
		iplist lt;
		lt.push_back(ip);
		m_mapURLtoIPtable[url] = lt;
	}

}
int CDnsImpl::getiptable(const char* url, const char* lastip, char* ip)
{
	retrtpv(url,0)
	retrtpv(ip,0)

	map<string, iplist>::iterator it = m_mapURLtoIPtable.find(url);
	if (it != m_mapURLtoIPtable.end()) {
		
		iplist find = (*it).second;
		iplist::iterator itlist = find.begin();

		while (itlist != find.end()) {

			if (strcmp((*itlist).c_str(), lastip) != 0) {
				strncpy(ip, (*itlist).c_str(), (*itlist).length());
				return 1;
			}
			itlist++;
		}
	}
	return 0;
}
//////////////////////////////////////////////////////////////////////////



